using DocumentCreationSystem.Models;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

namespace DocumentCreationSystem.Services
{
    /// <summary>
    /// 项目扫描服务
    /// </summary>
    public class ProjectScanService
    {
        private readonly ILogger<ProjectScanService> _logger;

        // 支持的文档文件扩展名
        private readonly HashSet<string> _documentExtensions = new(StringComparer.OrdinalIgnoreCase)
        {
            ".md", ".txt", ".docx", ".doc", ".pdf", ".rtf"
        };

        // 支持的代码文件扩展名
        private readonly HashSet<string> _codeExtensions = new(StringComparer.OrdinalIgnoreCase)
        {
            ".cs", ".js", ".ts", ".py", ".java", ".cpp", ".c", ".h", ".html", ".css", ".xml", ".json"
        };

        // 需要忽略的目录
        private readonly HashSet<string> _ignoredDirectories = new(StringComparer.OrdinalIgnoreCase)
        {
            "bin", "obj", "node_modules", ".git", ".vs", ".vscode", "packages", "target", "build"
        };

        public ProjectScanService(ILogger<ProjectScanService> logger)
        {
            _logger = logger;
        }

        /// <summary>
        /// 扫描指定目录下的所有项目
        /// </summary>
        /// <param name="rootPath">根目录路径</param>
        /// <param name="maxDepth">最大扫描深度</param>
        /// <returns>项目扫描结果</returns>
        public async Task<ProjectScanResult> ScanProjectsAsync(string rootPath, int maxDepth = 3)
        {
            var stopwatch = Stopwatch.StartNew();
            var result = new ProjectScanResult();

            try
            {
                _logger.LogInformation($"开始扫描项目，根目录: {rootPath}，最大深度: {maxDepth}");

                if (!Directory.Exists(rootPath))
                {
                    result.Errors.Add($"目录不存在: {rootPath}");
                    return result;
                }

                await ScanDirectoryAsync(rootPath, 0, maxDepth, result);

                // 按类型和活跃度排序
                result.Projects = result.Projects
                    .OrderByDescending(p => p.IsActive)
                    .ThenBy(p => p.Type)
                    .ThenBy(p => p.Name)
                    .ToList();

                stopwatch.Stop();
                result.ScanDuration = stopwatch.Elapsed;

                _logger.LogInformation($"项目扫描完成，找到 {result.Projects.Count} 个项目，耗时 {result.ScanDuration.TotalMilliseconds:F0}ms");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "扫描项目时发生错误");
                result.Errors.Add($"扫描错误: {ex.Message}");
            }

            return result;
        }

        /// <summary>
        /// 递归扫描目录
        /// </summary>
        private async Task ScanDirectoryAsync(string directoryPath, int currentDepth, int maxDepth, ProjectScanResult result)
        {
            if (currentDepth > maxDepth)
                return;

            try
            {
                var dirInfo = new DirectoryInfo(directoryPath);
                if (_ignoredDirectories.Contains(dirInfo.Name))
                    return;

                result.ScannedDirectories++;

                // 分析当前目录是否为项目
                var projectInfo = await AnalyzeDirectoryAsync(directoryPath);
                if (projectInfo != null)
                {
                    result.Projects.Add(projectInfo);
                }

                // 继续扫描子目录
                var subdirectories = Directory.GetDirectories(directoryPath);
                foreach (var subdirectory in subdirectories)
                {
                    await ScanDirectoryAsync(subdirectory, currentDepth + 1, maxDepth, result);
                }
            }
            catch (UnauthorizedAccessException)
            {
                // 忽略无权限访问的目录
            }
            catch (Exception ex)
            {
                result.Errors.Add($"扫描目录 {directoryPath} 时出错: {ex.Message}");
            }
        }

        /// <summary>
        /// 分析目录是否为项目
        /// </summary>
        private async Task<ProjectInfo?> AnalyzeDirectoryAsync(string directoryPath)
        {
            try
            {
                var dirInfo = new DirectoryInfo(directoryPath);
                var files = dirInfo.GetFiles("*", SearchOption.TopDirectoryOnly);

                // 统计文件类型
                var markdownFiles = files.Where(f => f.Extension.Equals(".md", StringComparison.OrdinalIgnoreCase)).ToList();
                var documentFiles = files.Where(f => _documentExtensions.Contains(f.Extension)).ToList();
                var codeFiles = files.Where(f => _codeExtensions.Contains(f.Extension)).ToList();

                // 判断是否为项目（至少包含3个相关文件或有特定的项目标识文件）
                var isProject = false;
                var projectType = ProjectType.Unknown;

                // 检查是否有项目标识文件
                var hasProjectFile = files.Any(f => 
                    f.Name.Equals("README.md", StringComparison.OrdinalIgnoreCase) ||
                    f.Name.Equals("package.json", StringComparison.OrdinalIgnoreCase) ||
                    f.Name.EndsWith(".csproj", StringComparison.OrdinalIgnoreCase) ||
                    f.Name.EndsWith(".sln", StringComparison.OrdinalIgnoreCase));

                if (hasProjectFile)
                {
                    isProject = true;
                }
                else if (markdownFiles.Count >= 3)
                {
                    isProject = true;
                    projectType = ProjectType.MarkdownProject;
                }
                else if (documentFiles.Count >= 5)
                {
                    isProject = true;
                    projectType = ProjectType.DocumentProject;
                }
                else if (codeFiles.Count >= 3)
                {
                    isProject = true;
                    projectType = ProjectType.CodeProject;
                }

                if (!isProject)
                    return null;

                // 确定项目类型
                if (projectType == ProjectType.Unknown)
                {
                    if (markdownFiles.Count > documentFiles.Count && markdownFiles.Count > codeFiles.Count)
                        projectType = ProjectType.MarkdownProject;
                    else if (codeFiles.Count > documentFiles.Count)
                        projectType = ProjectType.CodeProject;
                    else if (documentFiles.Count > 0)
                        projectType = ProjectType.DocumentProject;
                    else
                        projectType = ProjectType.MixedProject;
                }

                // 检查是否为小说项目
                if (projectType == ProjectType.MarkdownProject || projectType == ProjectType.DocumentProject)
                {
                    var hasChapterFiles = files.Any(f => 
                        f.Name.Contains("章", StringComparison.OrdinalIgnoreCase) ||
                        f.Name.Contains("chapter", StringComparison.OrdinalIgnoreCase) ||
                        f.Name.Contains("第", StringComparison.OrdinalIgnoreCase));

                    if (hasChapterFiles)
                        projectType = ProjectType.NovelProject;
                }

                // 计算项目大小
                var totalSize = files.Sum(f => f.Length);

                // 获取主要文件
                var mainFiles = GetMainFiles(files, projectType);

                // 判断是否为活跃项目（最近30天内有修改）
                var isActive = files.Any(f => f.LastWriteTime > DateTime.Now.AddDays(-30));

                var projectInfo = new ProjectInfo
                {
                    Name = dirInfo.Name,
                    Path = directoryPath,
                    Type = projectType,
                    Description = await GenerateProjectDescriptionAsync(directoryPath, files, projectType),
                    CreatedTime = dirInfo.CreationTime,
                    LastModifiedTime = files.Any() ? files.Max(f => f.LastWriteTime) : dirInfo.LastWriteTime,
                    FileCount = files.Length,
                    MarkdownFileCount = markdownFiles.Count,
                    Size = totalSize,
                    IsActive = isActive,
                    MainFiles = mainFiles,
                    Tags = GenerateProjectTags(files, projectType)
                };

                return projectInfo;
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, $"分析目录 {directoryPath} 时出错");
                return null;
            }
        }

        /// <summary>
        /// 获取主要文件列表
        /// </summary>
        private List<string> GetMainFiles(FileInfo[] files, ProjectType projectType)
        {
            var mainFiles = new List<string>();

            // 添加README文件
            var readmeFile = files.FirstOrDefault(f => f.Name.StartsWith("README", StringComparison.OrdinalIgnoreCase));
            if (readmeFile != null)
                mainFiles.Add(readmeFile.Name);

            // 根据项目类型添加主要文件
            switch (projectType)
            {
                case ProjectType.MarkdownProject:
                case ProjectType.NovelProject:
                    mainFiles.AddRange(files
                        .Where(f => f.Extension.Equals(".md", StringComparison.OrdinalIgnoreCase))
                        .OrderBy(f => f.Name)
                        .Take(5)
                        .Select(f => f.Name));
                    break;

                case ProjectType.CodeProject:
                    mainFiles.AddRange(files
                        .Where(f => _codeExtensions.Contains(f.Extension))
                        .OrderBy(f => f.Name)
                        .Take(5)
                        .Select(f => f.Name));
                    break;

                case ProjectType.DocumentProject:
                    mainFiles.AddRange(files
                        .Where(f => _documentExtensions.Contains(f.Extension))
                        .OrderBy(f => f.Name)
                        .Take(5)
                        .Select(f => f.Name));
                    break;
            }

            return mainFiles.Distinct().ToList();
        }

        /// <summary>
        /// 生成项目描述
        /// </summary>
        private async Task<string> GenerateProjectDescriptionAsync(string directoryPath, FileInfo[] files, ProjectType projectType)
        {
            var description = projectType switch
            {
                ProjectType.MarkdownProject => $"包含 {files.Count(f => f.Extension.Equals(".md", StringComparison.OrdinalIgnoreCase))} 个Markdown文件",
                ProjectType.NovelProject => $"小说项目，包含 {files.Count(f => _documentExtensions.Contains(f.Extension))} 个章节文件",
                ProjectType.DocumentProject => $"文档项目，包含 {files.Count(f => _documentExtensions.Contains(f.Extension))} 个文档文件",
                ProjectType.CodeProject => $"代码项目，包含 {files.Count(f => _codeExtensions.Contains(f.Extension))} 个源代码文件",
                ProjectType.MixedProject => $"混合项目，包含 {files.Length} 个文件",
                _ => $"包含 {files.Length} 个文件"
            };

            return description;
        }

        /// <summary>
        /// 生成项目标签
        /// </summary>
        private List<string> GenerateProjectTags(FileInfo[] files, ProjectType projectType)
        {
            var tags = new List<string>();

            // 添加类型标签
            tags.Add(projectType.ToString());

            // 添加语言标签
            var extensions = files.Select(f => f.Extension.ToLower()).Distinct().ToList();
            if (extensions.Contains(".cs")) tags.Add("C#");
            if (extensions.Contains(".js")) tags.Add("JavaScript");
            if (extensions.Contains(".py")) tags.Add("Python");
            if (extensions.Contains(".md")) tags.Add("Markdown");

            // 添加大小标签
            var totalSize = files.Sum(f => f.Length);
            if (totalSize > 10 * 1024 * 1024) tags.Add("大型");
            else if (totalSize > 1024 * 1024) tags.Add("中型");
            else tags.Add("小型");

            return tags;
        }
    }
}
